<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import type { FormValidationError } from 'naive-ui';
import { useBoolean } from '@sa/hooks';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { fetchAddVPNTemplate, fetchEditVPNTemplate } from '@/service/api';
import {
  ahAuthAlgorithmOptions,
  encapsulationModeOptions,
  ikeEncryptAlgorithmOptions,
  ikeVerifyAlgorithmOptions,
  ikeVerifyMethodOptions,
  ikedhGroupOptions,
  ipsecAuthAlgorithmOptions,
  ipsecEncryptAlgorithmOptions,
  ipsecPfsOptions,
  ipsecTransformOptions,
  ipsecTypeOptions
} from '@/constants/business';

defineOptions({
  name: 'VPNTemplateOperateDrawer'
});

interface Props {
  /** 操作类型 */
  operateType: NaiveUI.TableOperateType;
  /** 编辑行数据 */
  rowData?: TicketManageApi.VPNTemplateManage.Template | null;
}

const props = defineProps<Props>();

type Tabs = 'ike-sa' | 'ipsec-sa' | 'params';
const defaultActiveTab: Tabs = 'ike-sa';
const activeTab = ref<Tabs>(defaultActiveTab); /** 选项卡 */

interface Emits {
  (e: 'submitted'): void;
}

const emit = defineEmits<Emits>();

const visible = defineModel<boolean>('visible', {
  default: false
});

const { bool: loading, setBool: setLoading } = useBoolean();

const { formRef, restoreValidation, getTabPanelByError } = useNaiveForm();
const { createRequiredRule, createRequiredNumRule, createLengthRule, createNumberRange } = useFormRules();

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增量子模板配置',
    edit: '编辑量子模板配置'
  };
  return titles[props.operateType];
});

type Model = CommonType.RecordNullable<
  Pick<
    TicketManageApi.VPNTemplateManage.Template,
    | 'id'
    | 'name'
    | 'ipsecType'
    | 'encapsulationMode'
    | 'ikeVerifyMethod'
    | 'ikeVerifyAlgorithm'
    | 'ikeEncryptAlgorithm'
    | 'ikedhGroup'
    | 'ikeType'
    | 'ipsecAuthAlgorithm'
    | 'ipsecEncryptAlgorithm'
    | 'ipsecPfs'
    | 'ipsecSatrafficPeriod'
    | 'ahAuthAlgorithm'
    | 'ipsecTransform'
    | 'ikeSaperiod'
    | 'ipsecSatimePeriod'
    | 'dpdEnable'
    | 'dpdDpdretry'
    | 'dpdThreshold'
  >
>;

/** 默认值 */
const defaultValue_ahAuthAlgorithm = ahAuthAlgorithmOptions[0].value;
/** IKE SA 时间生命周期 */
const default_ikeSaperiod = 24;
const ikeSaperiodRange = [1, 24];
/** IPSec SA生命周期 */
const default_ipsecSatimePeriod = 60;
const ipsecSatimePeriodRange = [5, 60];
/** DPD重传间隔 */
const default_dpdDpdretry = 5;
const dpdDpdRetryRange = [0, 5];
/** DPD空闲时间 */
const default_dpdThreshold = 25;
const dpdThresholdRange = [0, 25];

const model = ref(createDefaultModel());

function createDefaultModel() {
  return {
    id: null,
    name: '',
    ipsecType: 1,
    encapsulationMode: 1,
    /** IKE SA */
    ikeVerifyMethod: 2,
    ikeVerifyAlgorithm: 4,
    ikeEncryptAlgorithm: 6,
    ikedhGroup: 0,
    ikeType: '',
    ikeSaperiod: default_ikeSaperiod,
    /** IPSec SA */
    ipsecAuthAlgorithm: 4,
    ipsecEncryptAlgorithm: 5,
    ipsecPfs: 0,
    ipsecTransform: 2,
    ahAuthAlgorithm: defaultValue_ahAuthAlgorithm,
    ipsecSatimePeriod: default_ipsecSatimePeriod,
    ipsecSatrafficPeriod: 60,
    /** 参数 */
    dpdEnable: true,
    dpdDpdretry: default_dpdDpdretry,
    dpdThreshold: default_dpdThreshold
  };
}
/** tab 和 rulekey 对应关系 */
const validatorTabObj: Record<Tabs, RuleKey[]> = {
  'ike-sa': ['ikeVerifyMethod', 'ikeVerifyAlgorithm', 'ikeEncryptAlgorithm', 'ikedhGroup', 'ikeType', 'ikeSaperiod'],
  'ipsec-sa': [
    'ipsecAuthAlgorithm',
    'ipsecEncryptAlgorithm',
    'ipsecPfs',
    'ipsecTransform',
    'ahAuthAlgorithm',
    'ipsecSatimePeriod',
    'ipsecSatrafficPeriod'
  ],
  params: ['dpdDpdretry', 'dpdThreshold']
};

type RuleKey = Extract<
  keyof Model,
  | 'name'
  | 'ipsecType'
  | 'encapsulationMode'
  | 'ikeVerifyMethod'
  | 'ikeVerifyAlgorithm'
  | 'ikeEncryptAlgorithm'
  | 'ikedhGroup'
  | 'ikeType'
  | 'ipsecAuthAlgorithm'
  | 'ipsecEncryptAlgorithm'
  | 'ipsecPfs'
  | 'ipsecSatrafficPeriod'
  | 'ahAuthAlgorithm'
  | 'ipsecTransform'
  | 'ikeSaperiod'
  | 'ipsecSatimePeriod'
  | 'dpdDpdretry'
  | 'dpdThreshold'
>;

const rules: Record<RuleKey, CommonType.WithArray<App.Global.FormRule>> = {
  name: [createRequiredRule('请输入模板名称'), createLengthRule(64)],
  ipsecType: [createRequiredNumRule('请选择类型')],
  encapsulationMode: [createRequiredNumRule('请选择封包模式')],
  ikeVerifyMethod: [createRequiredNumRule('请选择IKE验证方法')],
  ikeVerifyAlgorithm: [createRequiredNumRule('请选择IKE验证算法')],
  ikeEncryptAlgorithm: [createRequiredNumRule('请选择IKE加密算法')],
  ikedhGroup: [createRequiredNumRule('请选择IKE组参数')],
  ikeType: [createRequiredRule('请输入IKE身份类型')],
  ipsecAuthAlgorithm: [createRequiredNumRule('请选择IPSec认证算法')],
  ipsecEncryptAlgorithm: [createRequiredNumRule('请选择IPSec加密算法')],
  ipsecPfs: [createRequiredNumRule('请选择IPSec DH组')],
  ipsecSatrafficPeriod: [createRequiredNumRule('请输入IPSec SA流量生命周期'), createNumberRange(0, 60)],
  ahAuthAlgorithm: [createRequiredNumRule('请选择AH认证算法')],
  ipsecTransform: [createRequiredNumRule('请选择IPSec封包协议')],
  ikeSaperiod: [
    createRequiredNumRule('请输入IKE SA时间生命周期'),
    createNumberRange(ikeSaperiodRange[0], ikeSaperiodRange[1])
  ],
  ipsecSatimePeriod: [
    createRequiredNumRule('请输入IPSec SA生命周期'),
    createNumberRange(ipsecSatimePeriodRange[0], ipsecSatimePeriodRange[1])
  ],
  dpdDpdretry: [
    createRequiredNumRule('请输入DPD重传间隔'),
    createNumberRange(dpdDpdRetryRange[0], dpdDpdRetryRange[1])
  ],
  dpdThreshold: [
    createRequiredNumRule('请输入DPD空闲时间'),
    createNumberRange(dpdThresholdRange[0], dpdThresholdRange[1])
  ]
};

function handleInitModel() {
  model.value = createDefaultModel();
  activeTab.value = defaultActiveTab;

  if (props.operateType === 'edit' && props.rowData) {
    Object.assign(model.value, props.rowData, {
      ikeSaperiod: props.rowData.ikeSaperiod / 60 / 60,
      ipsecSatimePeriod: props.rowData.ipsecSatimePeriod / 60
    });
  }
}

function closeDrawer() {
  visible.value = false;
}

async function handleSubmit() {
  formRef.value?.validate(async (errors: Array<FormValidationError> | undefined) => {
    if (errors) {
      const tabName = getTabPanelByError(errors, validatorTabObj);
      if (tabName) {
        activeTab.value = tabName;
      }
    } else {
      const params = { ...model.value } as TicketManageApi.VPNTemplateManage.Template;
      const { operateType } = props;
      const serviceMap = {
        add: fetchAddVPNTemplate,
        edit: fetchEditVPNTemplate
      };
      if (operateType === 'add') {
        delete params.id;
      }
      params.ikeSaperiod = params.ikeSaperiod * 60 * 60;
      params.ipsecSatimePeriod *= 60;
      setLoading(true);
      const { response, error } = await serviceMap[operateType](params);
      setLoading(false);
      if (error) return;
      window.$message?.success(response.data.msg);
      closeDrawer();
      emit('submitted');
    }
  });
}

function handleIpsecTransformChange() {
  model.value.ahAuthAlgorithm = defaultValue_ahAuthAlgorithm;
}

function handleDpdEnableChange() {
  model.value.dpdDpdretry = dpdDpdRetryRange[1];
  model.value.dpdThreshold = dpdThresholdRange[1];
}

watch(visible, () => {
  if (visible.value) {
    handleInitModel();
    restoreValidation();
  }
});
</script>

<template>
  <NDrawer v-model:show="visible" display-directive="show" :mask-closable="false" auto-focus :width="500">
    <NDrawerContent :title="title" :native-scrollbar="false" closable>
      <NForm ref="formRef" :model="model" :rules="rules">
        <NFormItem label="模板名称" path="name">
          <NInput v-model:value="model.name" placeholder="请输入模板名称" />
        </NFormItem>

        <NFormItem label="类型" path="ipsecType">
          <NSelect v-model:value="model.ipsecType" placeholder="请选择类型" :options="ipsecTypeOptions" />
        </NFormItem>

        <NFormItem label="封包模式" path="encapsulationMode">
          <NSelect
            v-model:value="model.encapsulationMode"
            placeholder="请选择封包模式"
            :options="encapsulationModeOptions"
          />
        </NFormItem>

        <NCard class="card-wrapper" content-style="padding: 0;">
          <NTabs v-model:value="activeTab" type="line" size="large" :tabs-padding="20" pane-style="padding: 20px;">
            <NTabPane name="ike-sa" tab="IKE SA协商" display-directive="show">
              <NFormItem label="IKE验证方法" path="ikeVerifyMethod">
                <NSelect
                  v-model:value="model.ikeVerifyMethod"
                  placeholder="请选择IKE验证方法"
                  :options="ikeVerifyMethodOptions"
                />
              </NFormItem>

              <NFormItem label="IKE验证算法" path="ikeVerifyAlgorithm">
                <NSelect
                  v-model:value="model.ikeVerifyAlgorithm"
                  placeholder="请选择IKE验证算法"
                  :options="ikeVerifyAlgorithmOptions"
                />
              </NFormItem>

              <NFormItem label="IKE加密算法" path="ikeEncryptAlgorithm">
                <NSelect
                  v-model:value="model.ikeEncryptAlgorithm"
                  placeholder="请选择IKE加密算法"
                  :options="ikeEncryptAlgorithmOptions"
                />
              </NFormItem>

              <NFormItem label="IKE组参数" path="ikedhGroup">
                <NSelect v-model:value="model.ikedhGroup" placeholder="请选择IKE组参数" :options="ikedhGroupOptions" />
              </NFormItem>

              <NFormItem label="IKE身份类型" path="ikeType">
                <NInput v-model:value="model.ikeType" placeholder="请选择IKE身份类型" />
              </NFormItem>

              <NFormItem label="IKE SA时间生命周期" path="ikeSaperiod">
                <NInputNumber
                  v-model:value="model.ikeSaperiod"
                  placeholder="请输入IKE SA时间生命周期"
                  :min="ikeSaperiodRange[0]"
                  :max="ikeSaperiodRange[1]"
                />
                <span class="m-l-8px">小时</span>
              </NFormItem>
            </NTabPane>

            <NTabPane name="ipsec-sa" tab="IPSec SA协商" display-directive="show">
              <NFormItem label="IPSec认证算法" path="ipsecAuthAlgorithm">
                <NSelect
                  v-model:value="model.ipsecAuthAlgorithm"
                  placeholder="请选择IPSec认证算法"
                  :options="ipsecAuthAlgorithmOptions"
                />
              </NFormItem>

              <NFormItem label="IPSec加密算法" path="ipsecEncryptAlgorithm">
                <NSelect
                  v-model:value="model.ipsecEncryptAlgorithm"
                  placeholder="请选择IPSec加密算法"
                  :options="ipsecEncryptAlgorithmOptions"
                />
              </NFormItem>

              <NFormItem label="IPSec DH组" path="ipsecPfs">
                <NSelect v-model:value="model.ipsecPfs" placeholder="请选择IPSec DH组" :options="ipsecPfsOptions" />
              </NFormItem>

              <NFormItem label="IPSec封包协议" path="ipsecTransform">
                <NSelect
                  v-model:value="model.ipsecTransform"
                  placeholder="请选择IPSec封包协议"
                  :options="ipsecTransformOptions"
                  @update:value="handleIpsecTransformChange"
                />
              </NFormItem>

              <NFormItem v-if="model.ipsecTransform === 1" label="AH认证算法" path="ahAuthAlgorithm">
                <NSelect
                  v-model:value="model.ahAuthAlgorithm"
                  placeholder="请选择AH认证算法"
                  :options="ahAuthAlgorithmOptions"
                />
              </NFormItem>

              <NFormItem label="IPSec SA生命周期" path="ipsecSatimePeriod">
                <NInputNumber
                  v-model:value="model.ipsecSatimePeriod"
                  placeholder="请输入IPSec SA生命周期"
                  :min="ipsecSatimePeriodRange[0]"
                  :max="ipsecSatimePeriodRange[1]"
                />
                <span class="m-l-8px">分钟</span>
              </NFormItem>

              <NFormItem label="IPSec SA流量生命周期" path="ipsecSatrafficPeriod">
                <NInputNumber
                  v-model:value="model.ipsecSatrafficPeriod"
                  placeholder="请输入IPSec SA流量生命周期"
                  :min="10"
                  :max="60"
                />
                <span class="m-l-8px">秒</span>
              </NFormItem>
            </NTabPane>

            <NTabPane name="params" tab="参数配置" display-directive="show">
              <NFormItem label="DPD启用状态" path="dpdEnable" label-placement="left">
                <NSwitch v-model:value="model.dpdEnable" @update:value="handleDpdEnableChange" />
              </NFormItem>

              <template v-if="model.dpdEnable">
                <NFormItem label="DPD重传间隔" path="dpdDpdretry">
                  <NInputNumber
                    v-model:value="model.dpdDpdretry"
                    placeholder="请输入DPD重传间隔"
                    :min="dpdDpdRetryRange[0]"
                    :max="dpdDpdRetryRange[1]"
                  />
                  <span class="m-l-8px">秒</span>
                </NFormItem>

                <NFormItem label="DPD空闲时间" path="dpdThreshold">
                  <NInputNumber
                    v-model:value="model.dpdThreshold"
                    placeholder="请输入DPD空闲时间"
                    :min="dpdThresholdRange[0]"
                    :max="dpdThresholdRange[1]"
                  />
                  <span class="m-l-8px">秒</span>
                </NFormItem>
              </template>
            </NTabPane>
          </NTabs>
        </NCard>
      </NForm>
      <template #footer>
        <NSpace :size="16">
          <NButton @click="closeDrawer">取消</NButton>
          <NButton type="primary" :loading="loading" @click="handleSubmit">确认</NButton>
        </NSpace>
      </template>
    </NDrawerContent>
  </NDrawer>
</template>

<style scoped></style>
